package cn.com.sbell.vss.csg.heartbeat;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.common.ByteBuffer;
import org.apache.mina.common.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;

public class VSHeartBeatMessageEncoder extends ProtocolEncoderAdapter {
	//private static Log logger = LogFactory.getLog(VSHeartBeatMessageEncoder.class);
	// 消息属性格式:return properties:Type-Reserved-Length-Value

	// 消息由消息头和消息体组成.消息体中包括多个消息属性.
	private final static int VERSION = 0x10;
	private final static int RESERVEDVALUE = 0;

	// 各消息属性type字段需要填的值
	private final static int ACK_TYPE = 0;
	private final static int SERVER_NAME = 1;
	private final static int SERVER_ID = 2;
	private final static int SERVER_IP = 3;
	private final static int INTERVAL = 4;
	// 增加设备接入码的属性值为9
	private final static int PU_PASSWORD = 9;
	private final static int SERVER_TYPE = 10;

	// 各个消息属性大小(字节)
	private final static int TYPE_LENGTH = 1;
	private final static int RESERVED_LENGTH = 1;
	private final static int LENGTH_LENGTH = 2;
	private final static int COMMON_PART_LENGTH = TYPE_LENGTH + RESERVED_LENGTH
			+ LENGTH_LENGTH;

	private final static int SERVERIP_IP_LENGTH = 4;
	private final static int SERVERIP_PORT_LENGTH = 2;
	private final static int SERVERIP_RESERVED_LENGTH = 2;
	private final static int SERVERIP_VALUE_LENGTH = SERVERIP_IP_LENGTH
			+ SERVERIP_PORT_LENGTH + SERVERIP_RESERVED_LENGTH;
	private final static int SERVERIP_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ SERVERIP_VALUE_LENGTH;

	private final static int SERVERID_VALUE_LENGTH = 10;
	private final static int SERVERID_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ SERVERID_VALUE_LENGTH;

	private final static int SERVERNAME_VALUE_LENGTH = 10;
	private final static int SERVERNAME_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ SERVERNAME_VALUE_LENGTH;

	private final static int ACCESSPWD_VALUE_LENGTH = 10;
	private final static int ACCESSPWD_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ ACCESSPWD_VALUE_LENGTH;

	private final static int SERVERTYPE_VALUE_LENGTH = 2;
	private final static int SERVERTYPE_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ SERVERTYPE_VALUE_LENGTH;

	private final static int INTERVAL_VALUE_LENGTH = 2;
	private final static int INTERVAL_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ INTERVAL_VALUE_LENGTH;

	private final static int ACKTYPE_VALUE_LENGTH = 1;
	private final static int ACKTYPE_TOTAL_LENGTH = COMMON_PART_LENGTH
			+ ACKTYPE_VALUE_LENGTH;

	// 消息总大小.
	private final static int HEAD_LENGTH = 4;
	private final static int BODY_LENGTH = SERVERIP_TOTAL_LENGTH
			+ SERVERID_TOTAL_LENGTH + SERVERNAME_TOTAL_LENGTH
			+ ACCESSPWD_TOTAL_LENGTH + SERVERTYPE_TOTAL_LENGTH
			+ INTERVAL_VALUE_LENGTH + ACKTYPE_VALUE_LENGTH;
	private final static int TOTAL_LENGTH = HEAD_LENGTH + BODY_LENGTH;

	public void encode(IoSession session, Object heartBeatMessage,
			ProtocolEncoderOutput out) throws Exception {
		//logger.info("Into the encode Method of VSHeartBeatMessageEncoder,the sesseion is " + session.getRemoteAddress());
		System.out.println("Into the encode Method of VSHeartBeatMessageEncoder,the sesseion is " + session.getRemoteAddress());
		if (heartBeatMessage instanceof HeartBeatMessage) {
			//logger.info("The message to encode is HeartBeatMessage");
			System.out.println("The message to encode is HeartBeatMessage");
			HeartBeatMessage msg = (HeartBeatMessage) heartBeatMessage;

			ByteBuffer buf = ByteBuffer.allocate(TOTAL_LENGTH);
			buf.setAutoExpand(true);

			// 消息头部分
			buf.put((byte) VERSION);// 版本号
			buf.put((byte) (msg.getMessageType()));// 请求的消息类型
			int totalLength = getTotalLength(msg);
			buf.putShort((short) totalLength);// 消息头和消息体的全部长度

			// 消息体部分
			// ACK_TYPE
			putACKTypeIntoBuffer(msg, buf);
			// INTERVAL
			putIntervalIntoBuffer(msg, buf);
			// SERVER_NAME
			if (null != msg.getServerName()) {
				putServerNameIntoBuffer(msg, buf);
			}
			// SERVER_ID
			if (null != msg.getServerId()) {
				putServerIdIntoBuffer(msg, buf);
			}
			// SERVER_IP
			if (null != msg.getServerIp()) {
				putServerIpIntoBuffer(msg, buf);
			}
			// PU_PASSWORD
			if (null != msg.getAccessPassword()) {
				putAccessPasswordIntoBuffer(msg, buf);
			}
			// SERVER_TYPE
			if (null != msg.getServerType()) {
				putServerTypeIntoBuffer(msg, buf);
			}
			// added vondart change total length
			buf.putShort(2, (short) buf.position());
			buf.flip();
			out.write(buf);
		}
	}

	private void putServerTypeIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		String serverType = msg.getServerType();
		putCommonPartIntoBuffer(buf, SERVER_TYPE, SERVERTYPE_TOTAL_LENGTH);
		buf.put(serverType.getBytes());
	}

	private void putACKTypeIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		boolean ackType = msg.isNeedAcknowledge();
		putCommonPartIntoBuffer(buf, ACK_TYPE, ACKTYPE_TOTAL_LENGTH);
		buf.putInt(ackType ? 1 : 0);
	}

	private void putServerNameIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		String serverName = msg.getServerName();
		putCommonPartIntoBuffer(buf, SERVER_NAME, SERVERNAME_TOTAL_LENGTH);
		buf.put(serverName.getBytes());
	}

	private void putServerIdIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		String serverId = msg.getServerId();
		putCommonPartIntoBuffer(buf, SERVER_ID, SERVERID_TOTAL_LENGTH);
		buf.put(serverId.getBytes());
	}

	private void putServerIpIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		String serverIp = msg.getServerIp();
		int port = msg.getPort();
		putCommonPartIntoBuffer(buf, SERVER_IP, SERVERIP_TOTAL_LENGTH);
		buf.put(serverIp.getBytes());
		buf.position(Integer.valueOf(port).byteValue());
	}

	private void putIntervalIntoBuffer(HeartBeatMessage msg, ByteBuffer buf) {
		int interval = msg.getPeriod();
		putCommonPartIntoBuffer(buf, INTERVAL, INTERVAL_TOTAL_LENGTH);
		buf.put(Integer.valueOf(interval).byteValue());
	}

	private void putAccessPasswordIntoBuffer(HeartBeatMessage msg,
			ByteBuffer buf) {
		String accessPassword = msg.getAccessPassword();
		putCommonPartIntoBuffer(buf, PU_PASSWORD, ACCESSPWD_TOTAL_LENGTH);
		buf.put(accessPassword.getBytes());
	}

	private int getTotalLength(HeartBeatMessage msg) {
		int totalLength = 0;
		totalLength += HEAD_LENGTH + ACKTYPE_TOTAL_LENGTH;
		if (null != msg.getServerName()) {
			totalLength += SERVERNAME_TOTAL_LENGTH;
		}
		if (null != msg.getServerId()) {
			totalLength += SERVERID_TOTAL_LENGTH;
		}
		if (null != msg.getServerIp()) {
			totalLength += SERVERIP_TOTAL_LENGTH;
		}
		if (null != msg.getServerType()) {
			totalLength += SERVERTYPE_TOTAL_LENGTH;
		}
		if (null != msg.getAccessPassword()) {
			totalLength += ACCESSPWD_TOTAL_LENGTH;
		}
		if (0 != msg.getPeriod()) {
			totalLength += INTERVAL_TOTAL_LENGTH;
		}
		return totalLength;
	}

	/*
	 * 消息属性公共部分:属性类型+保留字+消息属性长度
	 */
	private void putCommonPartIntoBuffer(ByteBuffer buf, int type,
			int totallength) {
		buf.put((byte) type);// 属性类型
		buf.put((byte) RESERVEDVALUE);// 保留字
		buf.putShort((short) totallength);// 消息属性长度
	}
}
